package org.wheel.plugins.toolkit.jdbc.pool.util;

import cn.hutool.core.util.StrUtil;
import org.springframework.jdbc.core.JdbcTemplate;
import org.wheel.plugins.toolkit.jdbc.pool.bean.DatabaseConnection;
import org.wheel.plugins.toolkit.jdbc.pool.spi.DataSourceFactory;

import javax.sql.DataSource;
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.ConcurrentHashMap;

/**
 * 动态连接池工具：支持多数据源，底层走 DataSourceFactory 策略
 * 默认内置 HikariCP 工厂，API 与旧版 100% 兼容
 */
public final class DynamicJdbcPoolUtil {

    /* ====== 单例：双重检查锁 ====== */
    private static volatile DynamicJdbcPoolUtil instance;
    public static DynamicJdbcPoolUtil getInstance() {
        if (instance == null) {
            synchronized (DynamicJdbcPoolUtil.class) {
                if (instance == null) {
                    instance = new DynamicJdbcPoolUtil();
                }
            }
        }
        return instance;
    }

    private DynamicJdbcPoolUtil() {}

    /* ====== 默认工厂：HikariCP ====== */
    private volatile DataSourceFactory dataSourceFactory = new DefaultHikariDataSourceFactory();

    /* ====== 允许替换工厂（仅一次即可） ====== */
    public void setDataSourceFactory(DataSourceFactory factory) {
        this.dataSourceFactory = Objects.requireNonNull(factory, "factory can't be null");
    }

    /* ====== 保留旧字段：默认数据源名称 ====== */
    private String defaultDataSourceName = "primary";

    public String getDefaultDataSourceName() {
        return defaultDataSourceName;
    }

    public void setDefaultDataSourceName(String defaultDataSourceName) {
        this.defaultDataSourceName = defaultDataSourceName;
    }

    /* ====== 缓存：name -> JdbcTemplate ====== */
    private static final Map<String, JdbcTemplate> jdbcTemplateMap = new ConcurrentHashMap<>();

    public void put(String name, JdbcTemplate tpl){
        jdbcTemplateMap.put(name, tpl);
    }
    /* ====== 核心 API：兼容旧版本 ====== */
    public JdbcTemplate getOrCreateJdbcTemplate(DatabaseConnection conn) {
        return jdbcTemplateMap.computeIfAbsent(conn.getName(),
                k -> createJdbcTemplate(conn));
    }

    public JdbcTemplate getJdbcTemplate(String name) {
        return jdbcTemplateMap.get(name);
    }

    public JdbcTemplate getDefaultJdbcTemplate() {
        return getJdbcTemplate(defaultDataSourceName);
    }

    /* ====== 关闭 ====== */
    public void closeJdbcTemplate(String name) {
        JdbcTemplate tpl = jdbcTemplateMap.remove(name);
        if (tpl != null) {
            DataSource ds = tpl.getDataSource();
            if (ds instanceof AutoCloseable closeable) {
                try {
                    closeable.close();
                } catch (Exception ignored) {}
            }
        }
    }

    public void closeAllJdbcTemplates() {
        jdbcTemplateMap.keySet().forEach(this::closeJdbcTemplate);
        jdbcTemplateMap.clear();
    }

    /* ====== 唯一改动点：用工厂创建 DataSource ====== */
    private JdbcTemplate createJdbcTemplate(DatabaseConnection conn) {
        DataSource ds = dataSourceFactory.createDataSource(conn);
        return new JdbcTemplate(ds);
    }

    /* ====== 默认工厂实现：HikariCP ====== */
    private static class DefaultHikariDataSourceFactory implements DataSourceFactory {
        @Override
        public DataSource createDataSource(DatabaseConnection conn) {
            if(StrUtil.isBlank(conn.getDriverClassName())){
                conn.setDriverClassName(DatabaseDriverUtil.getDriverByJdbcUrl(conn.getUrl()));
            }
            com.zaxxer.hikari.HikariConfig cfg = new com.zaxxer.hikari.HikariConfig();
            cfg.setJdbcUrl(conn.getUrl());
            cfg.setUsername(conn.getUsername());
            cfg.setPassword(conn.getPassword());
            cfg.setDriverClassName(conn.getDriverClassName());
            cfg.setPoolName("HikariCP-" + conn.getName());
            cfg.setMaximumPoolSize(10);
            cfg.setMinimumIdle(2);
            return new com.zaxxer.hikari.HikariDataSource(cfg);
        }
    }
}